/*
 * Copyright (C) 2006-2007 Eskil Bylund
 *
 * Based on code from MonoDevelop.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

using System;

using Gdk;
using Gtk;

namespace DCSharp.Gui
{
	public class DragNotebook : Notebook
    {
    	private bool startDrag;
		private bool dragInProgress;

		protected override bool OnButtonPressEvent(Gdk.EventButton evnt)
		{
			if (dragInProgress)
			{
				return base.OnButtonPressEvent(evnt);
			}

			if (evnt.Button == 1 && evnt.Type == EventType.ButtonPress
				&& FindTabAtPosition(evnt.XRoot, evnt.YRoot) >= 0)
			{
				startDrag = true;
			}
			return base.OnButtonPressEvent(evnt);
		}

		protected override bool OnButtonReleaseEvent(Gdk.EventButton evnt)
		{
			StopDrag(evnt.Time);

			return base.OnButtonReleaseEvent(evnt);
		}

		protected override bool OnMotionNotifyEvent(Gdk.EventMotion evnt)
		{
			if (!startDrag)
			{
				return base.OnMotionNotifyEvent(evnt);
			}

			if (!dragInProgress)
			{
				dragInProgress = true;
				Grab.Add(this);

				if (!Pointer.IsGrabbed)
				{
					Pointer.Grab(ParentWindow, false,
						EventMask.Button1MotionMask | EventMask.ButtonReleaseMask,
						null, new Cursor(CursorType.Fleur), evnt.Time);
				}
			}
			MoveTab(FindTabAtPosition(evnt.XRoot, evnt.YRoot));
			return true;
		}

		protected override bool OnKeyPressEvent(Gdk.EventKey evnt)
		{
			if (evnt.Key == Gdk.Key.Escape)
			{
				StopDrag(evnt.Time);
				return true;
			}
			return base.OnKeyPressEvent(evnt);
		}

		private void StopDrag(uint time)
		{
			if (Pointer.IsGrabbed)
			{
				Pointer.Ungrab(time);
				Grab.Remove(this);
			}

			startDrag = false;
			dragInProgress = false;
		}

		private void MoveTab(int destinationPage)
		{
			if (destinationPage >= 0 && destinationPage != CurrentPage)
			{
				ReorderChild(CurrentPageWidget, destinationPage);
			}
		}

		private int FindTabAtPosition(double cursorX, double cursorY)
		{
			int dragNotebookXRoot;
			int dragNotebookYRoot;
			int pageNumber = 0;
			int tabMaxX;
			int tabMaxY;
			int tabMinX;
			int tabMinY;

			Widget page = GetNthPage(0);
			Widget tab;

			ParentWindow.GetOrigin(out dragNotebookXRoot, out dragNotebookYRoot);

			while (page != null)
			{
				if ((tab = GetTabLabel(page)) == null)
				{
					return -1;
				}

				tabMinX = dragNotebookXRoot + tab.Allocation.X;
				tabMaxX = tabMinX + tab.Allocation.Width;

				tabMinY = dragNotebookYRoot + tab.Allocation.Y;
				tabMaxY = tabMinY + tab.Allocation.Height;

				if ((tabMinX <= cursorX) && (cursorX <= tabMaxX) &&
					(tabMinY <= cursorY) && (cursorY <= tabMaxY))
				{
					return pageNumber;
				}

				page = GetNthPage(++pageNumber);
			}

			return -1;
		}

	}
}
